package trilium

import (
	"context"
	"gitee.com/Luna-CY/hui-hui/internal/interface/application"
	"gitee.com/Luna-CY/hui-hui/internal/logger"
	"gitee.com/Luna-CY/hui-hui/internal/runtime"
	"gitee.com/Luna-CY/hui-hui/internal/util/archive"
	"gitee.com/Luna-CY/hui-hui/internal/util/downloader"
	"gitee.com/Luna-CY/hui-hui/internal/util/syscall"
	"math"
	"os"
	"path/filepath"
	"strings"
)

const packageAddress = "https://github.com/zadam/trilium/releases/download/v{version}/trilium-linux-x64-server-{version}.tar.xz"

func (cls *Trilium) Install(ctx context.Context, overwrite bool) error {
	if state, _, _, _, _ := cls.GetState(); application.Installed == state && !overwrite {
		logger.GetLogger().Sugar().Info("本地Trilium服务符合版本要求，取消安装")

		return nil
	}

	// 取锁
	cls.LockState()
	defer cls.UnlockState()

	cls.UpdateState(application.Installing, 0, "")
	cls.UpdateStageProgress("预清理本地Trilium服务安装路径", 0)

	// 完全删除Trilium服务器目录
	logger.GetLogger().Sugar().Info("预清理本地Trilium服务安装路径")
	if _, err := syscall.ExecuteCommandGetOutputIgnoreQuitCode(ctx, "rm", "-rf", rootPath); nil != err {
		cls.UpdateState(application.InstallFailure, 0, err.Error())

		return err
	}

	// 创建路径
	if err := os.MkdirAll(rootPath, 0755); nil != err {
		cls.UpdateState(application.InstallFailure, 0, err.Error())

		return err
	}

	cls.UpdateState(application.Installing, 30, "")
	cls.UpdateStageProgress("下载安装包", 0)

	// 下载文件
	var keywords = []string{"{version}", runtime.TriliumMinimumVersion}
	var address = strings.NewReplacer(keywords...).Replace(packageAddress)

	logger.GetLogger().Sugar().Infof("下载文件: %s", address)
	size, file, err := downloader.DownloadToTempFile(ctx, address, func(total int64, current int64) {
		cls.UpdateStageProgress("下载安装包", math.Ceil(float64(current)/float64(total)*10000)/100)
	})

	if nil != err {
		cls.UpdateState(application.InstallFailure, 30, err.Error())

		return err
	}

	defer func() {
		_ = os.RemoveAll(file.Name())
	}()

	cls.UpdateState(application.Installing, 50, "")
	cls.UpdateStageProgress("安装应用", 0)

	logger.GetLogger().Sugar().Infof("解压文件: %s", file.Name())
	if err := archive.DecompressTarXzFile(ctx, file, size, rootPath, func(total int64, current int64) {
		cls.UpdateStageProgress("安装应用", math.Ceil(float64(current)/float64(total)*10000)/100)
	}); nil != err {
		cls.UpdateState(application.InstallFailure, 50, err.Error())

		return err
	}

	cls.UpdateState(application.Installing, 70, "")
	cls.UpdateStageProgress("重置目录结构", 0)
	if _, err := syscall.ExecuteCommandGetOutputIgnoreQuitCode(ctx, "mv", filepath.Join(rootPath, "trilium-linux-x64-server", "*"), rootPath); nil != err {
		cls.UpdateState(application.InstallFailure, 70, err.Error())

		return err
	}

	// 初始化基础配置
	cls.UpdateState(application.Installing, 90, "")
	cls.UpdateStageProgress("清理旧的配置数据", 0)

	// 清理目录
	if err := os.RemoveAll(dataDir); nil != err {
		cls.UpdateState(application.InstallFailure, 90, err.Error())

		return err
	}

	// 重建目录
	if err := os.MkdirAll(filepath.Dir(configFilePath), 0755); nil != err {
		cls.UpdateState(application.InstallFailure, 90, err.Error())

		return err
	}

	cls.UpdateState(application.Installed, 100, "")
	cls.UpdateStageProgress("安装完成", 0)

	return nil
}
